home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / dviapollo / dvisuntool.c < prev    next >
C/C++ Source or Header  |  1990-10-01  |  27KB  |  874 lines

  1. /*
  2.   Modified on 27-Sep-87 by Leonard N. Zubkoff:
  3.     Modified for APOLLO.
  4. */
  5.  
  6.  /* @(#)dvisuntool.c    1.17 2/19/87 */
  7. #include "header.h"
  8. #include "genwindow.h"
  9. #define NEW(A) ((A *) malloc(sizeof(A)))
  10. /* #define DEBUG   1*/            /* for massive printing of input */
  11.                     /* trace information; select by -d */
  12.                     /* option before filename. */
  13. #ifdef DEBUG
  14. int Debug = 0;
  15. #endif
  16.  
  17. #define USEGLOBALMAG 1            /* when defined, the dvi global
  18.                           magnification is applied */
  19.  
  20. #define  FIRSTPXLCHAR      0
  21. #define  LASTPXLCHAR     127
  22. #define  NPXLCHARS       128
  23. #define  PXLID          1001
  24. #define  READ              4   /* for access() */
  25. #define  hconvRESOLUTION RESOLUTION /* These numbers are right for my */
  26. #define  vconvRESOLUTION RESOLUTION /* particular sun3 display.  TSF */
  27. #define BORDER_BLACK 3 /* Width of border, in pixels.*/
  28. #define PAGE_HEIGHT 11 /* Height of page, in inches. */
  29. #define PAGE_WIDTH 8.5 /* Width of page, in inches. */
  30. #define  STACKSIZE       100   /* This is bogus.  The DVI file gives */
  31.                    /* us a stacksize, we should use it.*/
  32.  
  33. #ifdef apollo
  34. #define  MAXOPEN 64     /* _NFILES     limit on number of open PXL files */
  35. #else
  36. #define  MAXOPEN 10     /* _NFILES     limit on number of open PXL files */
  37. #endif
  38.  
  39. float    ActualFactor();
  40. FILE*    fopen();
  41. void    draw_borders();
  42. void    fatal();
  43. void    FindPostAmblePtr();
  44. void    GetBytes();
  45. void    getfontdef();
  46. void    MoveDown();
  47. void    MoveOver();
  48. void    OpenFontFile();
  49. int    PixRound();
  50. int    ReadFontDef();
  51. int    readpostamble();
  52. void    SetChar();
  53. void    SetFntNum();
  54. void    SetRule();
  55. void    SkipFontDef();
  56. #ifndef apollo
  57. CharImage read_char();
  58. void show_char();
  59. #endif
  60. struct char_entry {        /* character entry */
  61. #ifndef apollo
  62.    unsigned short width, height;/* width and height in pixels */
  63.    short xOffset, yOffset;      /* x offset and y offset in pixels */
  64.    struct {
  65.        int isloaded;
  66.        union {
  67.      int fileOffset;
  68.      CharImage pixrectptr; /* Not a pixrect if we're
  69.                   using X! */
  70.        } address;
  71.    } where;
  72. #endif
  73.    int tfmw;            /* TFM width */
  74. };
  75.  
  76. struct font_entry {  /* font entry */
  77.    int k, c, s, d, a, l;
  78.    char n[STRSIZE];    /* FNT_DEF command parameters */
  79.    int font_space;    /* computed from FNT_DEF s parameter */
  80.    int font_mag;    /* computed from FNT_DEF s and d parameters */
  81.    char name[STRSIZE];    /* full name of PXL file */
  82.    FILE *font_file_id;  /* file identifier (0 if none) */
  83.    int magnification;    /* magnification read from PXL file */
  84.    int designsize;    /* design size read from PXL file */
  85.    struct char_entry ch[NPXLCHARS];/* character information */
  86.    struct font_entry *next;
  87. #ifdef apollo
  88.    short FontID;
  89. #endif
  90. };
  91.  
  92. struct pixel_list
  93. {
  94.     FILE *pixel_file_id;        /* file identifier */
  95.     int use_count;              /* count of "opens" */
  96.     struct font_entry *fptr     /* ptr to its font entry */
  97. };
  98.  
  99. int hconv; /*  DVI units per pixel */
  100. int vconv;
  101. int den;            /* denominator specified in preamble */
  102. struct font_entry *fontptr;     /* font_entry pointer for current font */
  103. struct font_entry *hfontptr=NULL;/* font_entry pointer for all fonts */
  104. struct font_entry *closedfonts=NULL; /* font_entry pointer for list of */
  105.                      /* closed fonts.  Hfontptr gets */
  106.                      /* put here when a file is */
  107.                      /* closed. */
  108. int h;                /* current horizontal position */
  109. int v;                /* current vertical position */
  110. int mag;            /* magnification specified in preamble */
  111. int nopen = 0;            /* number of open PXL files */
  112. int num;            /* numerator specified in preamble */
  113. struct font_entry *pfontptr = NULL; /* most recent font_entry pointer returned from OpenFontFile. */
  114. struct pixel_list pixel_files[MAXOPEN+1];
  115.                                 /* list of open PXL file identifiers */
  116.  
  117. long postambleptr;        /* Pointer to the postamble */
  118. FILE *pxlfp;            /* PXL file pointer */
  119.  
  120. /* This is called when a DVI file is closed.  It resets *hfontptr to */
  121.  /* NULL, and sets closedfonts to the old linked list stored in */
  122.  /* closedfonts appended with the value of hfontptr. */
  123. void close_fonts ()
  124. {
  125.   if (closedfonts == NULL) {
  126.     closedfonts = hfontptr;
  127.   } else {
  128.     struct font_entry *scanner;
  129.     for (scanner = closedfonts; scanner -> next != NULL; scanner =
  130.      scanner -> next);
  131.     scanner -> next = hfontptr;
  132.   };
  133.   hfontptr = NULL;
  134. }
  135.  
  136. int Nosignextend(fp, n)    /* return n byte quantity from file fp */
  137.      register FILE *fp;    /* file pointer    */
  138.      register int n;        /* number of bytes */
  139. {
  140.   register int x;        /* number being constructed */
  141.  
  142.   x = 0;
  143.   while (n--)  {
  144.     x <<= 8;
  145.     x |= getc(fp);
  146.   }
  147.   return(x);
  148. }
  149.  
  150. int signextend(fp, n)   /* return n byte quantity from file fp */
  151.      register FILE *fp;  /* file pointer    */
  152.      register int n;     /* number of bytes */
  153. {
  154.   int n1;            /* number of bytes        */
  155.   register int x;        /* number being constructed */
  156.  
  157.   x = getc(fp);            /* get first (high-order) byte */
  158.   n1 = n--;
  159.   while (n--)  {
  160.     x <<= 8;
  161.     x |= getc(fp);
  162.   }
  163.   /* NOTE: This code assumes that the right-shift is an arithmetic, rather
  164.      than logical, shift which will propagate the sign bit right.   According
  165.      to Kernighan and Ritchie, this is compiler dependent! */
  166.   /* Also, assuming sizeof(int) == 4 is machine dependent (32-bit ints) */
  167.   x<<=32-8*n1;
  168.   x>>=32-8*n1;            /* sign extend */
  169. #ifdef DEBUG
  170.   if (Debug)
  171.     {
  172.       fprintf(stderr,"\tsignextend(fp,%d)=%X\n",n1,x);
  173.     }
  174. #endif
  175.   return(x);
  176. }
  177.  
  178. /* This reads the stuff between the front of the dvi file and the */
  179.  /* start of the first page.  It returns the number of pages in the */
  180.  /* document. */
  181. int start_reading_dvi_file(dvifp)
  182.      FILE *dvifp;
  183. {
  184.   int pages;
  185.   fseek (dvifp, (long) 0, 0);
  186.   if ((Nosignextend(dvifp, 1)) != PRE)  {
  187.     fatal("PRE doesn't occur first. Are you sure this is a DVI file?");
  188.   }
  189.   {
  190.     int i;
  191.     i = signextend(dvifp, 1);
  192.     if (i != DVIFORMAT)  {
  193.       fatal ("DVI format = %d, can only process DVI format %d files\n\n",
  194.          i, DVIFORMAT);
  195.     }
  196.   }
  197.   pages = readpostamble (dvifp);
  198.   if (preload) getfontdef (dvifp);
  199.   fseek(dvifp, (long) 14, 0);
  200.   {
  201.     char n[STRSIZE];
  202.     GetBytes(dvifp, n, Nosignextend(dvifp, 1));
  203.   };
  204.   return (pages);
  205. }
  206.  
  207. /* Draw borders around the page.  Knuth says that the (0,0) point in */
  208.  /* DVI units should be one inch from the top and from the left edges */
  209.  /* of the page.  The page is 8.5 by 11 inches, of course. The borders */
  210.  /* are BORDER_BLACK pixels wide, and it lies just barely outside of the page.*/
  211. void draw_borders(xscreen, yscreen)
  212.      int xscreen, yscreen;
  213. {
  214.   int height = PAGE_HEIGHT * RESOLUTION; /* These are in pixels. */
  215.   int width = PAGE_WIDTH * RESOLUTION;
  216.   int x = - RESOLUTION - xscreen;
  217.   int  y = - RESOLUTION - yscreen;
  218.  
  219.   /* top horizontal */
  220.   black_box (x - BORDER_BLACK, y - BORDER_BLACK, 
  221.          width + 2 * BORDER_BLACK, BORDER_BLACK);
  222.   /* bottom horizontal */
  223.   black_box (x - BORDER_BLACK, y + height,
  224.          width + 2 * BORDER_BLACK, BORDER_BLACK);
  225.   /* left vertical */
  226.   black_box (x - BORDER_BLACK, y - BORDER_BLACK,
  227.          BORDER_BLACK, height + 2 * BORDER_BLACK);
  228.   /* right vertical */
  229.   black_box (x + width, y - BORDER_BLACK, 
  230.          BORDER_BLACK,  height + 2 * BORDER_BLACK);
  231. }
  232.  
  233. void showpage (cpagep, ppagep, SkipMode, PagesLeft, borders, dvifp, xscreen, yscreen)
  234.      long *cpagep, *ppagep;
  235.      int SkipMode, PagesLeft;
  236.      BOOLEAN borders; /* Whether to draw borders.*/
  237.      FILE *dvifp;
  238.      int xscreen, yscreen;
  239. {
  240.   int w;            /* current horizontal spacing */
  241.   int x;            /* current horizontal spacing */
  242.   int y;            /* current vertical spacing */
  243.   int z;            /* current vertical spacing */
  244.   int sp;            /* stack pointer */
  245.   struct stack_entry {        /* stack entry */
  246.     int h, v, w, x, y, z;    /* what's on stack */
  247.   };
  248.   struct stack_entry stack[STACKSIZE]; /* stack */
  249.   int SkipEOP = FALSE;        /* input is waiting from the terminal, skip to EOP */
  250.   int command; /* current command */
  251.  
  252.   w = x = y = z = 0; /*Let's hope that each page specifies values for */
  253.              /*w,x,y,and z before it uses them.  Sincx Knuth */
  254.              /*says that DVI format should be readable from */
  255.              /*back to front, this seems reasonable.*/
  256.   do {
  257.     command = Nosignextend(dvifp, 1);
  258.     switch (command)  {
  259.     case SET1:case SET2:case SET3:case SET4:
  260.       {int val;
  261.        val = Nosignextend(dvifp, command-SET1+1);
  262.        if (!SkipMode) SetChar(val, command, xscreen, yscreen);}
  263.       break;
  264.     case SET_RULE:
  265.       {int val, val2;
  266.        val = Nosignextend(dvifp, 4);
  267.        val2 = Nosignextend(dvifp, 4);
  268.        if (!SkipMode) SetRule(val, val2, 1, xscreen, yscreen);}
  269.       break;
  270.     case PUT1:case PUT2:case PUT3:case PUT4:
  271.       {int val;
  272.        val = Nosignextend(dvifp,command-PUT1+1);
  273.        if (!SkipMode) SetChar(val, command, xscreen, yscreen);}
  274.       break;
  275.     case PUT_RULE:
  276.       {int val, val2;
  277.        val = Nosignextend(dvifp, 4);
  278.        val2 = Nosignextend(dvifp, 4);
  279.        if (!SkipMode) SetRule(val, val2, 0, xscreen, yscreen);}
  280.       break;
  281.     case NOP:
  282.       break;
  283.     case BOP:
  284.       (*cpagep) = ftell(dvifp) - 1;
  285.       {int i;
  286.        for (i=0; i<=9; i++)
  287.      Nosignextend(dvifp, 4);}
  288.       (*ppagep) = Nosignextend(dvifp, 4);
  289.       h = v = w = x = y = z = 0;
  290.       sp = 0;
  291.       fontptr = NULL;
  292.       if (PagesLeft) {
  293.     PagesLeft--;
  294.     if (PagesLeft <= 0) SkipMode = FALSE;
  295.       };
  296.       break;
  297.     case EOP:
  298.       if (borders && !SkipMode && !SkipEOP)
  299.     draw_borders(xscreen, yscreen);
  300.       if (SkipEOP) { SkipMode = FALSE; SkipEOP = FALSE; }
  301.       break;
  302.     case PUSH:
  303.       if (sp >= STACKSIZE)
  304.     fatal("stack overflow");
  305.       stack[sp].h = h;
  306.       stack[sp].v = v;
  307.       stack[sp].w = w;
  308.       stack[sp].x = x;
  309.       stack[sp].y = y;
  310.       stack[sp].z = z;
  311.       sp++;
  312.       break;
  313.     case POP:
  314.       --sp;
  315.       if (sp < 0)
  316.     fatal("stack underflow");
  317.       h = stack[sp].h;
  318.       v = stack[sp].v;
  319.       w = stack[sp].w;
  320.       x = stack[sp].x;
  321.       y = stack[sp].y;
  322.       z = stack[sp].z;
  323.       break;
  324.     case RIGHT1:case RIGHT2:case RIGHT3:case RIGHT4:
  325.       {int val;
  326.        val = signextend(dvifp,command-RIGHT1+1);
  327.        if (!SkipMode) MoveOver(val);}
  328.       break;
  329.     case W0:
  330.       if (!SkipMode) MoveOver(w);
  331.       break;
  332.     case W1:case W2:case W3:case W4:
  333.       w = signextend(dvifp,command-W1+1);
  334.       if (!SkipMode) MoveOver(w);
  335.       break;
  336.     case X0:
  337.       if (!SkipMode) MoveOver(x);
  338.       break;
  339.     case X1:case X2:case X3:case X4:
  340.       x = signextend(dvifp,command-X1+1);
  341.       if (!SkipMode) MoveOver(x);
  342.       break;
  343.     case DOWN1:case DOWN2:case DOWN3:case DOWN4:
  344.       {int val;
  345.        val = signextend(dvifp,command-DOWN1+1);
  346.        if (!SkipMode) MoveDown(val);}
  347.       break;
  348.     case Y0:
  349.       if (!SkipMode) MoveDown(y);
  350.       break;
  351.     case Y1:case Y2:case Y3:case Y4:
  352.       y = signextend(dvifp,command-Y1+1);
  353.       if (!SkipMode) MoveDown(y);
  354.       break;
  355.     case Z0:
  356.       if (!SkipMode) MoveDown(z);
  357.       break;
  358.     case Z1:case Z2:case Z3:case Z4:
  359.       z = signextend(dvifp,command-Z1+1);
  360.       if (!SkipMode) MoveDown(z);
  361.       break;
  362.     case FNT1:case FNT2:case FNT3:case FNT4:
  363.       if (!SkipMode) SetFntNum(Nosignextend(dvifp,command-FNT1+1));
  364.       break;
  365.     case XXX1:case XXX2:case XXX3:case XXX4:
  366.       {int k;
  367.        k = Nosignextend(dvifp,command-XXX1+1);
  368.        while (k--)
  369.      Nosignextend(dvifp, 1);}
  370.       break;
  371.     case FNT_DEF1:case FNT_DEF2:case FNT_DEF3:case FNT_DEF4:
  372.       if (preload) {
  373.     SkipFontDef (Nosignextend(dvifp, command-FNT_DEF1+1), dvifp);
  374.       } else {
  375.     ReadFontDef (Nosignextend(dvifp, command-FNT_DEF1+1), dvifp);
  376.       }
  377.       break;
  378.     case PRE:
  379.       fatal("PRE occurs within file");
  380.       break;
  381.     case POST:
  382.       fseek(dvifp, (*cpagep), 0);
  383.       SkipMode = FALSE;
  384.       PagesLeft = 0;
  385.       break;
  386.     case POST_POST:
  387.       fatal("POST_POST with no preceding POST");
  388.       break;
  389.     default:
  390.       if (command >= FONT_00 && command <= FONT_63)
  391.      {if (!SkipMode) SetFntNum(command - FONT_00);}
  392.       else if (command >= SETC_000 && command <= SETC_127)
  393.     {if (!SkipMode) SetChar(command - SETC_000, command, xscreen, yscreen);}
  394.       else
  395.     fatal("%d is an undefined command", command);
  396.       break;
  397.     }                /* case */
  398.   } while (command != EOP || SkipMode);
  399. }
  400.  
  401. /* compute the actual size factor given the approximation */
  402. float ActualFactor(unmodsize)
  403. int unmodsize;  /* actually factor * 1000 */
  404. {
  405.   float realsize;        /* the actual magnification factor */
  406.  
  407.   realsize = (float)unmodsize / 1000.0;
  408.   /* a real hack to correct for rounding in some cases--rkf */
  409.   if(unmodsize==1095) realsize = 1.095445; /*stephalf*/
  410.   else if(unmodsize==1315) realsize=1.314534; /*stepihalf*/
  411.   else if(unmodsize==2074) realsize=2.0736; /*stepiv*/
  412.   else if(unmodsize==2488) realsize=2.48832; /*stepv*/
  413.   else if(unmodsize==2986) realsize=2.985984; /*stepiv*/
  414.   /* the remaining magnification steps are represented with sufficient
  415.      accuracy already */
  416.   return(realsize);
  417. }
  418.  
  419. int DoConv(num, den, convResolution)
  420. {
  421.     register float conv;
  422.     conv = ((float)num/(float)den) * 
  423. #ifdef USEGLOBALMAG
  424.       ActualFactor(mag) *          /* put back in by clp, 8/22/84 */
  425. /*    ((float) mag/1000.0) *           and this taken out...         */
  426. #endif
  427.     ((float)convResolution/254000.0);
  428.     return((int) (1.0 / conv + 0.5));
  429. }
  430.  
  431. void fatal(fmt, args)/* issue a fatal error message */
  432.      char *fmt;    /* format */
  433.      char *args; /* arguments */
  434. {
  435.     fprintf(stderr, "Fatal error.  ");
  436.     _doprnt(fmt, &args, stderr);
  437.     fprintf(stderr, "\n");
  438.     exit(1);
  439. }
  440.  
  441. void FindPostAmblePtr(postambleptr, dvifp)
  442.      long *postambleptr;
  443.      FILE *dvifp;
  444. /* this routine will move to the end of the file and find the start
  445.     of the postamble */
  446. {
  447.     int     i;
  448.  
  449.     fseek (dvifp, (long) 0, 2);   /* goto end of file */
  450.     *postambleptr = ftell (dvifp) - 4;
  451.     fseek (dvifp, *postambleptr, 0);
  452.  
  453.     while (TRUE) {
  454.     fseek (dvifp, --(*postambleptr), 0);
  455.     if (((i = Nosignextend(dvifp, 1)) != 223) &&
  456.         (i != DVIFORMAT))
  457.         fatal ("Bad end of DVI file");
  458.     if (i == DVIFORMAT)
  459.         break;
  460.     }
  461.     fseek (dvifp, (*postambleptr) - 4, 0);
  462.     *postambleptr = Nosignextend(dvifp, 4);
  463.     fseek (dvifp, *postambleptr, 0);
  464. }
  465.  
  466. void GetBytes(fp, cp, n)    /* get n bytes from file fp */
  467.      register FILE *fp;    /* file pointer     */
  468.      register char *cp;    /* character pointer */
  469.      register int n; /* number of bytes  */
  470. {
  471.     while (n--)
  472.     *cp++ = getc(fp);
  473. }
  474.  
  475. void getfontdef(dvifp)
  476.      FILE *dvifp;
  477. /* Read the font  definitions as they  are in the  postamble of the  DVI
  478.    file.  Note that the font directory  is not yet loaded.  In order  to
  479.    adapt ourselves to the existing "verser" the following font paramters
  480.    are  copied     onto  output    fontno  (4   bytes),  chksum,    fontmag,
  481.    fontnamelength (1 byte), fontname.  At the end, a -1 is put onto  the
  482.    file.*/
  483. {
  484.     char    str[50], *calloc ();
  485.     unsigned char   byte;
  486.     int     i, fnamelen;
  487.  
  488.     while (((byte = Nosignextend(dvifp, 1)) >= FNT_DEF1) &&
  489.     (byte <= FNT_DEF4)) {
  490.     switch (byte) {
  491.     case FNT_DEF1:
  492.         ReadFontDef (Nosignextend(dvifp, 1), dvifp);
  493.         break;
  494.     case FNT_DEF2:
  495.         ReadFontDef (Nosignextend(dvifp, 2), dvifp);
  496.         break;
  497.     case FNT_DEF3:
  498.         ReadFontDef (Nosignextend(dvifp, 3), dvifp);
  499.         break;
  500.     case FNT_DEF4:
  501.         ReadFontDef (Nosignextend(dvifp, 4), dvifp);
  502.         break;
  503.     default:
  504.         fatal ("Bad byte value in font defs");
  505.         break;
  506.     }
  507.     }
  508.     if (byte != POST_POST)
  509.     fatal ("POST_POST missing after fontdefs");
  510. }
  511.  
  512. void MoveDown(a)
  513. int a;
  514. {
  515.   v += a;
  516. }
  517.  
  518. void MoveOver(b)
  519. int b;
  520. {
  521.     h += b;
  522. }
  523.  
  524. void OpenFontFile()
  525. /* The original version of this dvi driver reopened the font file  each
  526.    time the font changed, resulting in an enormous number of relatively
  527.    expensive file  openings.   This version  keeps  a cache  of  up  to
  528.    MAXOPEN open files,  so that when  a font change  is made, the  file
  529.    pointer, pxlfp, can  usually be  updated from the  cache.  When  the
  530.    file is not found in  the cache, it must  be opened.  In this  case,
  531.    the next empty slot  in the cache  is assigned, or  if the cache  is
  532.    full, the least used font file is closed and its slot reassigned for
  533.    the new file.  Identification of the least used file is based on the
  534.    counts of the number  of times each file  has been "opened" by  this
  535.    routine.  On return, the file pointer is always repositioned to  the
  536.    beginning of the file.*/
  537. {
  538.     register int i,least_used,current;
  539.  
  540. #ifdef DEBUG
  541.     if (Debug) printf("Open Font file\n");
  542. #endif
  543.     if (pfontptr == fontptr)
  544.         return;                 /* we need not have been called */
  545.  
  546.     for (current = 1;
  547.     (current <= nopen) &&
  548.         (pixel_files[current].pixel_file_id != fontptr->font_file_id);
  549.     ++current); /* try to find file in open list */
  550.     if (current <= nopen) {      /* file already open */
  551.     pxlfp = pixel_files[current].pixel_file_id;
  552.     fseek(pxlfp,0,0);    /* reposition to start of file */
  553.     } else {                        /* file not in open list */
  554.         if (nopen < MAXOPEN)    /* just add it to list */
  555.             current = ++nopen;
  556.     else {/* list full -- find least used file, close it, and */
  557.           /* reuse slot for new file */ 
  558.         least_used = 1;
  559.             for (i = 2; i <= MAXOPEN; ++i)
  560.             if (pixel_files[least_used].use_count >
  561.                     pixel_files[i].use_count)
  562.             least_used = i;
  563.         fclose(pixel_files[least_used].pixel_file_id);
  564.         pixel_files[least_used].fptr -> font_file_id = 0;
  565.         current = least_used;
  566.         }
  567.         if ((pxlfp=fopen(fontptr->name,"r")) == NULL) {
  568.       perror ("");
  569.       fatal("PXL file \"%s\" could not be opened; %d PXL files are open",
  570.         fontptr->name,nopen);
  571.     };
  572.     pixel_files[current].pixel_file_id = pxlfp;
  573.     pixel_files[current].fptr = fontptr;
  574.     pixel_files[current].use_count = 0;
  575.     }
  576.     pfontptr = fontptr;            /* make previous = current font */
  577.     fontptr->font_file_id = pxlfp;    /* set file identifier */
  578.     pixel_files[current].use_count++;    /* update reference count */
  579. }
  580.  
  581. int PixRound(x, conv)    /* return rounded number of pixels */
  582.      register int x;        /* in DVI units     */
  583.      int conv;        /* conversion factor */
  584. {
  585.   return((int)((x + (conv >> 1)) / conv));
  586. }
  587.  
  588. /* Put the given font pointer on the global list of font pointers and */
  589.  /* make it the current font. */
  590. void installfontptr (tfontptr)
  591.      struct font_entry *tfontptr;
  592. {
  593.   tfontptr->next = hfontptr;
  594.   fontptr = hfontptr = tfontptr;
  595. }
  596.  
  597. int ReadFontDef(k, dvifp)
  598.      int k;
  599.      FILE *dvifp;
  600. {
  601.   int t, i;
  602.   register struct font_entry *tfontptr;    /* temporary font_entry pointer   */
  603.   register struct char_entry *tcharptr;    /* temporary char_entry pointer  */
  604.   char *direct, *tcp, *tcp1;
  605.   int found;
  606.   char curarea[STRSIZE];
  607.  
  608.   if ((tfontptr = NEW(struct font_entry)) == NULL)
  609.     fatal("can't malloc space for font_entry");
  610.  
  611.   tfontptr->k = k;
  612.   tfontptr->c = Nosignextend(dvifp, 4);    /* checksum */
  613.   tfontptr->s = Nosignextend(dvifp, 4);    /* space size */
  614.   tfontptr->d = Nosignextend(dvifp, 4);    /* design size */
  615.   tfontptr->a = Nosignextend(dvifp, 1);    /* area length for font name */
  616.   tfontptr->l = Nosignextend(dvifp, 1);    /* device length */
  617.   GetBytes(dvifp, tfontptr->n, tfontptr->a+tfontptr->l);
  618.   tfontptr->n[tfontptr->a+tfontptr->l] = '\0';
  619.   tfontptr->font_space = tfontptr->s/6;    /* never used */
  620.   tfontptr->font_mag = (int)((ActualFactor((int)(((float)tfontptr->s/
  621.                           (float)tfontptr->d)*1000.0 + 0.5)) * 
  622. #ifdef USEGLOBALMAG
  623.                   ActualFactor(mag) *
  624. #endif
  625.                   (float)RESOLUTION * 5.0) + 0.5);
  626.  
  627. #ifdef DEBUG
  628.   printf ("Trying to open font %s, mag %d.\n", tfontptr -> n, 
  629.       tfontptr -> font_mag);
  630. #endif
  631.   /* Look for a font with the same file name as tfontptr in */
  632.   /* closedfonts. */
  633.   {
  634.     struct font_entry *prevptr=NULL; /* Follows curptr in the closed */
  635.     /* fonts list. */
  636.     struct font_entry *curptr;
  637.     for (curptr = closedfonts;
  638.      (curptr != NULL) &&
  639.      !((curptr->font_mag == tfontptr -> font_mag) &&
  640.        (strcmp (curptr -> n, tfontptr -> n) == 0));
  641.      prevptr = curptr,curptr = curptr -> next);
  642.     if (curptr != NULL) {
  643. #ifdef DEBUG
  644.       printf ("Re-opening closed font %s, mag %d, filename is %s.\n",
  645.           tfontptr -> n, tfontptr -> font_mag, curptr -> name);
  646. #endif
  647.       /* We found a font with the same name in the list of closed */
  648.       /* fonts.  Now delete it from the list of closed fonts. */
  649.       if (prevptr == NULL) {
  650.     /* curptr was the first font on the list of closed fonts. */
  651.     closedfonts = closedfonts -> next;
  652.       } else {
  653.     /* curptr wasn't first. */
  654.     prevptr -> next = curptr -> next;
  655.       };
  656.       /* Verify that all of the relevant font parameters are the */
  657.       /* same. */
  658.       if ((tfontptr -> c != curptr -> c) ||
  659.       (tfontptr -> s != curptr -> s) ||
  660.       (tfontptr -> d != curptr -> d)) {
  661.       fatal ("Font %s at magnification %d reencountered with different parameters.",
  662.          tfontptr -> n, tfontptr -> font_mag);
  663.     };
  664.       curptr -> k = tfontptr -> k;
  665.       /* The following is somewhat bogus.  I should fix the above */
  666.       /* code so that no mallocs happen if the font is in the closed */
  667.       /* list.  Oh well, spaghetti code begats spaghetti code. */
  668.       free (tfontptr);
  669.       installfontptr (curptr);
  670.     } else {
  671.       /* Opening a new font. */
  672.       if (tfontptr->a != 0) {
  673. #ifndef apollo
  674.     sprintf(tfontptr->name, "%s.%dpxl", tfontptr->n, tfontptr->font_mag);
  675. #else
  676.     sprintf(tfontptr->name, "%s.%daaf", tfontptr->n, tfontptr->font_mag);
  677. #endif
  678.       } else {
  679. #ifndef apollo
  680.     direct = PXLpath;
  681. #else
  682.     direct = AAFpath;
  683. #endif
  684.     found = FALSE;
  685.     do { 
  686.       tcp = index(direct, ':');
  687.       if (tcp == NULL) tcp = strlen(direct) + direct;
  688.       strncpy(curarea, direct, tcp-direct);
  689.       tcp1 = curarea + (tcp - direct);
  690.       *tcp1++ = '/';
  691.       *tcp1++ = '\0';
  692.  
  693. #ifndef apollo
  694.       sprintf(tfontptr->name, "%s%s.%dpxl", curarea, tfontptr->n, tfontptr->font_mag);
  695. #else
  696.       sprintf(tfontptr->name, "%s%s.%daaf", curarea, tfontptr->n, tfontptr->font_mag);
  697. #endif
  698.       found = (access(tfontptr->name, READ) == 0);
  699.       if (*tcp) direct = tcp + 1; else direct = tcp;
  700.     } while ( !found && *direct != '\0');
  701. #ifdef apollo
  702.     tfontptr->FontID = LoadFontFile(tfontptr->name);
  703. #endif
  704.       };
  705. #ifdef DEBUG
  706.       printf ("Filename is %s.\n", tfontptr -> name);
  707. #endif
  708.       installfontptr (tfontptr);
  709.       OpenFontFile();
  710. #ifndef apollo
  711.       if ((t = Nosignextend(pxlfp, 4)) != PXLID)
  712.     fatal("PXL ID = %d, can only process PXL ID = %d files",
  713.           t, PXLID);
  714. #else
  715.       fseek(pxlfp, -4, 2);
  716.       if ((t = Nosignextend(pxlfp, 4)) != PXLID)
  717.     fatal("PXL ID = %d, can only process PXL ID = %d files",
  718.           t, PXLID);
  719. #endif
  720.       fseek(pxlfp, -20, 2);
  721.       t = Nosignextend(pxlfp, 4);
  722.       if ((tfontptr->c != 0) && (t != 0) && (tfontptr->c != t))
  723.     fatal("font = \"%s\",\n-->font checksum = %d,\n-->dvi checksum = %d",
  724.           tfontptr->name, tfontptr->c, t);
  725.       tfontptr->magnification = Nosignextend(pxlfp, 4);
  726.       tfontptr->designsize = Nosignextend(pxlfp, 4);
  727.  
  728. #ifndef apollo
  729.       fseek(pxlfp, Nosignextend(pxlfp, 4) * 4, 0);
  730. #else
  731.       fseek(pxlfp, -532, 2);
  732. #endif
  733.  
  734.  
  735.       for (i = FIRSTPXLCHAR; i <= LASTPXLCHAR; i++) {
  736.     tcharptr = &(tfontptr->ch[i]);
  737. #ifndef apollo
  738.     tcharptr->width = Nosignextend(pxlfp, 2);
  739.     tcharptr->height = Nosignextend(pxlfp, 2);
  740.     tcharptr->xOffset= signextend(pxlfp, 2);
  741.     tcharptr->yOffset = signextend(pxlfp, 2);
  742.     tcharptr->where.isloaded = FALSE;
  743.     tcharptr->where.address.fileOffset = Nosignextend(pxlfp, 4) * 4;
  744. #endif
  745.     tcharptr->tfmw = ((float)Nosignextend(pxlfp, 4)*(float)tfontptr->s) /
  746.       (float)(1<<20);
  747.       }
  748.     }
  749.   }
  750. }
  751.  
  752. int readpostamble (dvifp)
  753.      FILE *dvifp;
  754. /* This  routine  is  used  to  read  in  the  postamble  values.    It
  755.    initializes the magnification and checks  the stack height prior  to
  756.    starting printing the document.  It returns the number of pages in the document. */
  757. {
  758.     FindPostAmblePtr (&postambleptr, dvifp);
  759.     if (Nosignextend(dvifp, 1) != POST)
  760.     fatal ("POST missing at head of postamble");
  761. #ifdef DEBUG
  762.     if (Debug) fprintf (stderr, "got POST command\n");
  763. #endif
  764.     /*      lastpageptr = */ Nosignextend(dvifp, 4);
  765.     num = Nosignextend(dvifp, 4);
  766.     den = Nosignextend(dvifp, 4);
  767.     mag = Nosignextend(dvifp, 4);
  768.     hconv = DoConv(num, den, hconvRESOLUTION);
  769.     vconv = DoConv(num, den, vconvRESOLUTION);
  770.  
  771.     Nosignextend(dvifp, 4);    /* height-plus-depth of tallest page */
  772.     Nosignextend(dvifp, 4);    /* width of widest page */
  773.     if (Nosignextend(dvifp, 2) >= STACKSIZE)
  774.     fatal ("Stack size is too small");
  775.     return (Nosignextend(dvifp, 2));    /* this reads the number of pages in */
  776.     /* the DVI file */
  777. }
  778.  
  779. #ifndef apollo
  780. void LoadAChar(ptr)
  781.      register struct char_entry *ptr;
  782. {
  783.   if (ptr->where.address.fileOffset == 0) {
  784.     ptr->where.address.pixrectptr = NULL;
  785.     return;
  786.   }
  787.   OpenFontFile();
  788.   fseek(pxlfp, ptr->where.address.fileOffset, 0);
  789.   ptr->where.address.pixrectptr =
  790.     read_char (pxlfp, ptr -> width, ptr -> height);
  791.   ptr->where.isloaded = TRUE;
  792. }
  793. #endif
  794.  
  795. /* Display a character.*/
  796. void SetChar(c, command, xscreen, yscreen)
  797.      int c; /* Character to display */
  798.      int command; /* Command we are doing */
  799.      int xscreen, yscreen;
  800. {
  801.   register struct char_entry *ptr; /* temporary char_entry pointer */
  802.   int k;
  803.   int hh; /* current horizontal position in pixels */
  804.   int vv; /* current vertical position in pixels */
  805.  
  806.   ptr = &(fontptr->ch[c]);
  807.   hh = PixRound(h, hconv);
  808.   vv = PixRound(v, vconv);
  809. #ifdef apollo
  810.   DrawCharacter(c,hh-xscreen,vv-yscreen,fontptr->FontID);
  811. #else
  812.   if (!ptr->where.isloaded) LoadAChar(ptr);
  813.   show_char (hh-ptr->xOffset-xscreen, vv-ptr->yOffset-yscreen,
  814.          ptr->width, ptr->height,
  815.          ptr->where.address.pixrectptr);
  816. #endif
  817.   if (command <= SET4) h += ptr->tfmw;
  818. }
  819.  
  820. void SetFntNum(k)
  821.      int k;
  822. /*  this routine is used to specify the font to be used in printing future
  823.     characters */
  824. {
  825.     fontptr = hfontptr;
  826.     while ((fontptr!=NULL) && (fontptr->k!=k))
  827.     fontptr = fontptr->next;
  828.     if (fontptr == NULL)
  829.     fatal("font %d undefined", k);
  830. }
  831.  
  832. void SetRule(a, b, Set, xscreen, yscreen)
  833.      int a, b;
  834.      BOOLEAN Set;
  835.      int xscreen, yscreen;
  836. {        /*     this routine will draw a rule on the screen */
  837.     int ehh, evv;
  838.     int hh; /* current horizontal position in pixels */
  839.   int vv; /* current vertical position in pixels */
  840.  
  841.     hh = PixRound(h, hconv);
  842.     vv = PixRound(v-a, vconv);
  843.     ehh = PixRound(h + b, hconv);
  844.     evv = PixRound(v, vconv);
  845.     if (hh == ehh) ehh++;
  846.     if (vv == evv) vv--;
  847.     if ((a > 0) && (b > 0))
  848. #ifdef apollo
  849.       black_box (hh-xscreen, vv-yscreen+2, ehh-hh, evv-vv);
  850. #else
  851.       black_box (hh-xscreen, vv-yscreen, ehh-hh, evv-vv);
  852. #endif
  853.     if (Set) {
  854.     h += b;
  855. /*        v += a; */
  856.     }
  857. }
  858.  
  859. void SkipFontDef(k, dvifp)
  860.      int k;
  861.      FILE *dvifp;
  862. {
  863.   int a, l;
  864.   char n[STRSIZE];
  865.  
  866.   Nosignextend(dvifp, 4);
  867.   Nosignextend(dvifp, 4);
  868.   Nosignextend(dvifp, 4);
  869.   a = Nosignextend(dvifp, 1);
  870.   l = Nosignextend(dvifp, 1);
  871.   GetBytes(dvifp, n, a+l);
  872. }
  873.  
  874.